# This Python file uses the following encoding: utf-8
# ##############################################################################
# Copyright (c) 2025 Li Auto Inc. and its affiliates
# Licensed under the Apache License, Version 2.0(the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ##############################################################################
"""
CANTRCV1145配置代码和配置文件生成模块.
"""
import os
import inspect
from . import filter
from . import context
from func_module.health_monitor.logger import logger
from jinja2 import Environment, FileSystemLoader, StrictUndefined, UndefinedError, Template

CUR_FILE_PATH = os.path.dirname(__file__)
DEFAULT_TEMPLATE_FILE_DIR = os.path.join(CUR_FILE_PATH, "template")


def generate_dynamic_code(sys_config: dict, config_dict: dict):
    """
    generate CanTrcv_Tja1145_*.c/h code
    """
    output_file_dir = os.path.join(sys_config["gendata_path"])
    input_dict = filter.get_template_input_parameter_dict(sys_config, config_dict)
    config_dict = {
        "template_dir": DEFAULT_TEMPLATE_FILE_DIR,
        "output_dir": output_file_dir,
        "input_dict": input_dict,
        "sys_config": sys_config
    }

    # Build our rendering environment.
    env = Environment(loader=FileSystemLoader(os.path.abspath(DEFAULT_TEMPLATE_FILE_DIR)), undefined=StrictUndefined)
    env.filters.update(context.get_filters())
    env.globals.update(context.get_functions())

    # Create required directories
    cantrcv1145_output_dir = os.path.realpath(os.path.join(config_dict["output_dir"], "CanTrcv1145"))
    # logger.info(f"Creating {cantrcv1145_output_dir} directories if they don't already exist")
    os.makedirs(cantrcv1145_output_dir, exist_ok=True)

    # Render all of the files.
    # We use a gross while True loop to allow state.additional_files to
    # be appended to as it is processed.

    template_file_list = env.list_templates()
    template_dict = {}
    for template_file in template_file_list:
        template_dict[template_file] = env.get_template(template_file)
    try:
        render_files(sys_config, template_dict, config_dict)
    except UndefinedError as e:
        # find the error location in the template
        error_info = None
        frame_info_list = inspect.trace()
        frame_info_list.reverse()
        for frame_info in frame_info_list:
            if frame_info.function == "top-level template code":
                error_info = frame_info
                break
        filename = os.path.basename(error_info.filename)
        error_line = error_info.lineno
        error_code = error_info.code_context[0].strip()
        logger.error(f"UndefinedError: {filename}:{error_line} {error_code} {e}")
        return False
    return True


def render_files(sys_config, template_dict, config_dict):
    """
    Render template_file.
    """
    output_dir = config_dict.get("output_dir")
    if output_dir is None:
        logger.error("Output directory is not set in config")

    input_dict = config_dict["input_dict"]
    render_cantrcv1145_cfg_file(sys_config, template_dict, input_dict, output_dir)
    render_cantrcv1145_pbcfg_file(sys_config, template_dict, input_dict, output_dir)

def render_cantrcv1145_cfg_file(sys_config, template_dict, input_dict, output_dir):
    """
    Render cantrcv_tja1145_cfg.c/h template file.
    """
    template: Template = template_dict.get("cantrcv_tja1145_cfg.c.jinja2")
    if template is not None:
        file_path = os.path.join(output_dir, "CanTrcv1145/cantrcv_tja1145_cfg.c")
        logger.debug("Start generating cantrcv_tja1145_cfg.c file")
        # print("file_path: ", file_path)
        with open(file_path, "w", encoding="utf-8") as out_stream:
            # process template file
            config = {
                "sys_cfg": sys_config,
                "input_dict": input_dict,
                "CanTrcvChannel": input_dict["CanTrcvChannel"],
                "CanTrcvGeneral": input_dict["CanTrcv1145_Genernal"],
                "CanTrcvConfigSet": input_dict["CanTrcv1145_ConfigSet_dict"],
                "spi_channel_prefix": input_dict["spi_channel_prefix"],
                "spi_sequence_prefix": input_dict["spi_sequence_prefix"],
                # "CanTrcvPnCfg": input_dict["CanTrcvChannel"]["CanTrcvPaitialNetwork"],
            }
            # print("CanTrcvChannel: ", input_dict["CanTrcvChannel"])

            out_stream.write(template.render(config))
            logger.info("Finish generating cantrcv_tja1145_cfg.c file")

    template = template_dict.get("cantrcv_tja1145_cfg.h.jinja2")
    if template is not None:
        file_path = os.path.join(output_dir, "CanTrcv1145/cantrcv_tja1145_cfg.h")
        # print("file_path: ", file_path)
        logger.debug("Start generating cantrcv_tja1145_cfg.h file")
        with open(file_path, "w", encoding="utf-8") as out_stream:
            # process template file
            config = {
                "sys_cfg": sys_config,
                "input_dict": input_dict,
                "CanTrcvChannel": input_dict["CanTrcvChannel"],
                "CanTrcvGeneral": input_dict["CanTrcv1145_Genernal"],
                "CanTrcvConfigSet": input_dict["CanTrcv1145_ConfigSet_dict"],
            }
            out_stream.write(template.render(config))
            logger.info("Finish generating cantrcv_tja1145_cfg.h file")


def render_cantrcv1145_pbcfg_file(sys_config, template_dict, input_dict, output_dir):
    """
    Render  cantrcv_tja1145_pbcfg.c/h template file.
    """
    template: Template = template_dict.get("cantrcv_tja1145_pbcfg.c.jinja2")
    if template is not None:
        file_path = os.path.join(output_dir, "CanTrcv1145/cantrcv_tja1145_pbcfg.c")
        # print("file_path: ", file_path)
        logger.debug("Start generating cantrcv_tja1145_pbcfg.c file")
        with open(file_path, "w", encoding="utf-8") as out_stream:
            # process template file
            config = {
                "sys_cfg": sys_config,
                "input_dict": input_dict,
            }
            out_stream.write(template.render(config))
            logger.info("Finish generating cantrcv_tja1145_pbcfg.c file")

    template: Template = template_dict.get("cantrcv_tja1145_pbcfg.h.jinja2")
    if template is not None:
        file_path = os.path.join(output_dir, "CanTrcv1145/cantrcv_tja1145_pbcfg.h")
        # print("file_path: ", file_path)
        logger.debug("Start generating cantrcv_tja1145_pbcfg.h file")
        with open(file_path, "w", encoding="utf-8") as out_stream:
            # process template file
            config = {
                "sys_cfg": sys_config,
                "input_dict": input_dict,
            }
            out_stream.write(template.render(config))
            logger.info("Finish generating cantrcv_tja1145_pbcfg.h file")